import config
import os
import copy


class Game:
    def __init__(self):
        self.__max_size = config.max_size
        self.__field = config.field 
        self.__X_axis = config.X_axis
        self.__Y_axis = config.Y_axis
        self.__number_step = 0
        self.__current_size = 0
        self.__mod = 0

    @property
    def max_size(self):
        return self.__max_size

    @property
    def number_step(self):
        return self.__number_step

    @property
    def current_size(self):
        return self.__current_size

    @property
    def mod(self):
        return self.__mod

    def draw_field(self):   
        if self.__number_step / self.__current_size**2 >= 0.2:
            self.__current_size = min(self.__max_size, self.__current_size + 1)

        print('{:>4}'.format(''), end='')
        for i in range(self.__current_size):
            print(self.__X_axis[i], end=' ')

        print()
        for i in range(self.__current_size):
            print('{:<4}'.format(self.__Y_axis[i]), end='')
            for j in range(self.__current_size):
                if (j+1) % self.__current_size == 0:
                    print(self.__field[i][j])
                else:
                    print(self.__field[i][j], end=' ')

    def check_win(self, coord, player, mod):
        if mod == 1:
            limit_l = -2
            limit_r = 3
            len_line = 3
        else :
            limit_l = -4
            limit_r = 5
            len_line = 5
            
        x = int(coord[1])-1
        y = ord(coord[0])-65
        line = ''

        if self.__number_step == self.__max_size**2:
            return 2
        
        line = ''.join(self.__field[x][max(0, y+limit_l):min(self.__current_size, y+limit_r)])
        if line.count(player*len_line) > 0:
            return 1
        
        line = ''
        for i in range(max(0, y+limit_l), min(y+limit_r, self.__current_size)):
            line += self.__field[i][y]    
        if line.count(player*len_line) > 0:
                return 1
        
        line = ''
        for i in range(limit_l, limit_r):
            if 0 <= x+i < self.__current_size and 0 <= y+i < self.__current_size:
                line += self.__field[x+i][y+i]
            else:
                continue
        if line.count(player*len_line) > 0:
            return 1
        
        line = ''
        for i in range(limit_l, limit_r):
            if 0 <= x-i < self.__current_size and 0 <= y+i < self.__current_size:
                line += self.__field[x-i][y+i]
            else:
                continue
        if line.count(player*len_line) > 0:
            return 1

        return 0

    def process_error(self, coord):
        if len(coord) == 0:
            return 'Entered coordinates are incorrect, input coordinates again'
        elif len(coord) == 2:
           if (coord[0] not in self.__X_axis[:self.__current_size+1] and len(coord[0]) == 1) or coord[1] not in self.__Y_axis[:self.__current_size+1]:
                return 'Entered coordinates are incorrect, input coordinates again'

        if self.__field[int(coord[1])-1][ord(coord[0])-65] != '_':
            return "This cell is't empty"
        
        return 229

    def step(self, player):
        coord = tuple([_.upper() for _ in input("Input coordinates draw {}: ".format(player)).split()]) 
        if len(coord) == 1:
            tmp = coord[0] 
            x = tmp[0]
            y = tmp[1:]
            coord = (x, y)
        
        mess = self.process_error(coord)
        if mess == 229:
           self.__field[int(coord[1])-1][ord(coord[0])-65] = player  
        else:
            os.system('clear')
            self.draw_field()
            print(mess)
            return self.step(player)

        self.__number_step += 1
        os.system('clear')
        self.draw_field()
        return self.check_win(coord, player, self.__mod)

    def restart_game(self):
        ch = input("1. Restart Game\n0. Exit Game\n")
        if ch == '1':
            os.system('clear')
            return self.main()
        if ch == '0':
            os.system('clear')
            exit()
        else:
            return self.restart_game()

    def menu(self):
        print('Choose game mode')
        ch = input('1. 3x3\n2. 5x5-12x12\n')
        if ch == '1':
            self.__max_size = 3
            self.__current_size = 3
            self.__number_step = 0
            self.__field = copy.deepcopy(config.field)
            self.__mod = 1
        elif ch == '2':
            self.__max_size = 12
            self.__current_size = 5
            self.__number_step = 0
            self.__field = copy.deepcopy(config.field)
            self.__mod = 2
        else:
            return self.menu()
        os.system('clear')
        
    def main(self): 
        self.menu()
        result = 0
        player = 'X' 
        self.draw_field()
        while result == 0:
            result = self.step(player)
            if player == "X" and result == 0: player = "O"
            elif player == "O" and result == 0: player = "X"
        if result == 1:
            print('We have a winner! {} win!'.format(player))
        elif result == 2:
            print('Draw')
        self.restart_game()

